package oleg.match; 

/**
 * Copyright 2008 Oleg Frenkel
 *
 * This file is part of PerfectSearch.
 *
 * PerfectSearch is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PerfectSearch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PerfectSearch.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.util.*;
import javax.microedition.pim.Contact;

import oleg.C;
import oleg.ContactUtils;
import oleg.cfg.Config;
import oleg.locale.StringNormalizer;
import oleg.log.Logger;

/**
 * This is the most straightforward implementation. 
 * No performance tuning (including cache) is used in this implementation.
 */

public class Matcher0 implements IMatcher
{
  private ContactUtils contUtils = new ContactUtils();
  private Vector allContacts;
  private Vector matchingStartNameContacts = new Vector();
  private Vector matchingContacts = new Vector();
//   private String inputText = "";
//   private int padMode = -1;
  
  public Matcher0(Vector allContacts) {
    setAllContacts(allContacts);
  }

  public void setAllContacts(Vector allContacts) {
    this.allContacts = allContacts;    
    matchingStartNameContacts.removeAllElements();
    matchingContacts.removeAllElements();
  }

  public void clearCache() {
    
  }

  public void updateMatchingContacts(String inputText) {
    matchingStartNameContacts.removeAllElements();
    matchingContacts.removeAllElements();

    // Logger.log("Matcher0: allContacts");
    // testPrint(allContacts);
    for (int i = 0; i < allContacts.size(); i++) {
      Contact curCont = (Contact)allContacts.elementAt(i);

      // if (i==4 || i==5) {
      //   Logger.log("contact for " + i + ": " + curCont.getString(Contact.FORMATTED_NAME, 0));
      //   Logger.log("match type: " + matchContact(curCont, inputText));
      // }

      switch (matchContact(curCont, inputText)) {
        case C.START_MATCH:
          matchingStartNameContacts.addElement(curCont);
          break;
        case C.CONTAIN_MATCH:
          matchingContacts.addElement(curCont);
          break;
      }
    }
  }

  private void testPrint(Vector allContacts) {
    Logger.log("Number of elements: " + allContacts.size());
    for (int i = 0; i < allContacts.size(); i++) {
      Contact c = (Contact)allContacts.elementAt(i);
      String s = c.getString(Contact.FORMATTED_NAME, 0);
      if ("Aggarwal Rakesh".equals(s)) {
        Logger.log("Rakesh index: " + i);
      }
    }
  }  

  public Vector getMatchingStartNameContacts() {
    return matchingStartNameContacts;
  }

  public Vector getMatchingContacts() {
    return matchingContacts;
  }

  public String getDisplayText(Contact curCont, String inputText) {
    switch (Config.instance().getPadMode()) {
    case C.PAD_MODE_PRED_OFF:
    case C.PAD_MODE_NUM:
      return inputText;
    case C.PAD_MODE_PRED_ON:
      if (curCont == null) {
//         return "NO MATCHES";
        return inputText;
      }

      String startsStr = startsWith(curCont, Contact.NAME, inputText);
      if (startsStr != null) {
        return startsStr;
      } else {
        int[] allFields = curCont.getPIMList().getSupportedFields();
        for (int j = 0; j < allFields.length; j++) {
          int curField = allFields[j];
          String containsStr = contains(curCont, curField, inputText);
          if (containsStr != null) {
            return containsStr;
          }
        }
      }

      return inputText;
    }

    throw new RuntimeException("Unknown pad mode: " + Config.instance().getPadMode());
  }

  public int matchContact(Contact curCont, String inputText) {
    int padMode = Config.instance().getPadMode();
    if (padMode == C.PAD_MODE_PRED_ON && curCont == null) {
      return C.NO_MATCH;
    }

    if (startsWith(curCont, Contact.NAME, inputText) != null ||
        startsWith(curCont, Contact.FORMATTED_NAME, inputText) != null) 
    {
      return C.START_MATCH;
    } else {
      int[] allFields = curCont.getPIMList().getSupportedFields();
      for (int j = 0; j < allFields.length; j++) {
        int curField = allFields[j];
        if (contains(curCont, curField, inputText) != null) {
          return C.CONTAIN_MATCH;
        }
      }
      
      return C.NO_MATCH;
    }
  }

  private String startsWith(Contact curCont, int field, String inputText) {
    String locale = Config.instance().getWritingLang();
    StringNormalizer strNormalizer = StringNormalizer.instance(locale);
    Vector values = contUtils.getValuesAsVector(curCont, field);
//     Logger.log("Matcher0.startsWith: values.size(): " + values.size());
    for (int i = 0; i < values.size(); i++) {
      String curValue = (String)values.elementAt(i);
      String normCurValue = strNormalizer.normalize(curValue);
//       Logger.log("Matcher0: curValue: " +
//                  curValue + " normCurValue: " + normCurValue);
      if (normCurValue == null) {
        return null;
      }
      if (normCurValue.startsWith(inputText)) {
//         Logger.log("Matcher0.startsWith: curValue: " +
//                    curValue + " normCurValue: " + normCurValue +
//                    " inputText: " + inputText +
//                    " return: " + curValue.substring(0, inputText.length()));
        return curValue.substring(0, inputText.length());
      }
    }

    return null;
  }

  private String contains(Contact curCont, int field, String inputText) {
    String locale = Config.instance().getWritingLang();
    StringNormalizer strNormalizer = StringNormalizer.instance(locale);
    Vector values = contUtils.getValuesAsVector(curCont, field);
    for (int i = 0; i < values.size(); i++) {
      String curValue = (String)values.elementAt(i);
      String normCurValue = strNormalizer.normalize(curValue);
      if (normCurValue == null) {
        return null;
      }
      int startInd = normCurValue.indexOf(inputText);
      if (startInd >= 0) {
        return curValue.substring(startInd, startInd + inputText.length());
      }
    }

    return null;
  }

}